import { event,debugLogger } from '../utils/index.js'

export function initTiming(_this, isPerformanceFlag, _set_) {
  if (!isPerformanceFlag) {
    debugLogger.call(_this, 'config.performance值为false, 跳过性能指标打点')
    return;
  }
 
  //获取性能相关参数
  if (!performance || !PerformanceObserver)
    throw "该浏览器不支持该performance方法";
  //性能指标
  getPerformance(_set_);
  event(() => {
    //用户体验指标
    let reload = performance.getEntries()[0];
    const {
      connectEnd,
      connectStart,
      responseStart,
      requestStart,
      responseEnd,
      loadEventStart,
      // domContentLoadedEventEnd,
      // domContentLoadedEventStart,
      domInteractive,
      fetchStart,
      domainLookupEnd,
      domainLookupStart,
    } = reload;
    let experienceMap = {
      DNSTime: domainLookupEnd - domainLookupStart, //DNS查询耗时	如果使用长连接或本地缓存，则数值为0
      TCPconnectTime: connectEnd - connectStart, //TCP连接建立的时间
      TTFBTime: responseStart - requestStart, //首字节到达时间 ,请求响应耗时
      responseTime: responseEnd - responseStart, //响应的读取时间
      DOMTime: domInteractive - responseEnd, //DOM解析耗时
      // domContentLoadedTime:domContentLoadedEventEnd - domContentLoadedEventStart, //DOM解析的时间
      timeToInteractive: domInteractive - fetchStart, //首次可交互时间
      loadTIme: loadEventStart - fetchStart, //页面完全加载时间
    };
    // 收集上报信息
    _set_.addSub({ experienceMap });
  });
}
const getPerformance = async (_set_) => {
  // 非阻塞型监控
  await get_FP(_set_.addSub)
  await get_FCP(_set_.addSub)
  await get_LCP(_set_.addSub)
  // // 阻塞型监控
  await get_FID(_set_.addSub)
  await get_CLS(_set_.addSub)
};

// 获取（fp）(白屏时间)
const get_FP = (addSub) => {
  return new Promise((resolve, reject) => {
    const observer = new PerformanceObserver((list) => {
      for (const entry of list.getEntries()) {
        if (entry.name === "first-paint") {
          //白屏时间 fp
          addSub({
            performanceMap: [
              {
                type: "first-paint",
                time: entry.startTime,
              },
            ],
          });
          resolve({
            type: "first-paint",
            time: entry.startTime,
          });
          observer.disconnect();
        }
      }
    });
    observer.observe({ type: "paint", buffered: true });
  });
};
// 获取 首次内容渲染（fcp)(灰屏时间) -1800-3000-
const get_FCP = (addSub) => {
  return new Promise((resolve, reject) => {
    const observer = new PerformanceObserver((list) => {
      for (const entry of list.getEntries()) {
        if (entry.name === "first-contentful-paint") {
          //首屏时间 fcp
          addSub({
            performanceMap: [
              {
                type: "first-contentful-paint",
                time: entry.startTime,
              },
            ],
          });
          resolve({
            type: "first-contentful-paint",
            time: entry.startTime,
          });
          observer.disconnect();
        }
      }
    });
    observer.observe({ type: "paint", buffered: true });
  });
};
//获取LCP最大内容绘制是页面内首次开始加载的时间点，到 可视区域内最大的图像或者文本块完成渲染 的 相对时间-2500-4000-
const get_LCP = (addSub) => {
  return new Promise((resolve, reject) => {
    const entryHandler = (list) => {
      if (observer) {
        observer.disconnect();
      }

      for (const entry of list.getEntries()) {
        addSub({
          performanceMap: [
            {
              type: "largest-contentful-paint",
              time: entry.startTime,
            },
          ],
        });
        resolve({
          type: "largest-contentful-paint",
          time: entry.startTime,
        });
      }
    };
    const observer = new PerformanceObserver(entryHandler);
    observer.observe({ type: "largest-contentful-paint", buffered: true });
  });
};
// FID 是从用户第一次与页面交互（例如当他们单击链接、点按按钮或使用由 JavaScript 驱动的自定义控件）-100-300-
const get_FID = (addSub) => {
  return new Promise((resolve, reject) => {
    new PerformanceObserver((entryList) => {
      const entries = entryList.getEntries();
      const entry = entries[entries.length - 1];
      const delay = entry.processingStart - entry.startTime;
      addSub({
        performanceMap: [
          {
            type: "first-input",
            time: delay,
          },
        ],
      });
      resolve({
        type: "first-input",
        time: delay,
      });
    }).observe({ type: "first-input", buffered: true });
  });
};
// 获取累计布局偏移分数（布局偏移分数 = 影响分数 * 距离分数）CLS 就是把所有布局偏移分数加起来的总和
//  -0.1-0.25-
const get_CLS = () => {
  //取所有会话窗口中的最大值时间上报
  let sessionValue = 0;
  let sessionEntries = [];
  let clsValue = 0;
  return new Promise((resolve, reject) => {
    const entryHandler = (list) => {
      for (const entry of list.getEntries()) {
        // 只计算非人为操作的意外布局变化的布局移位。
        if (!entry.hadRecentInput) {
          const firstSessionEntry = sessionEntries[0];
          const lastSessionEntry = sessionEntries[sessionEntries.length - 1];
          // 如果该条目发生在前一个条目之后不到1秒，且在会话中的第一个条目之后不到5秒，则将该条目包含在当前会话中。否则，开始一个新的会话。
          if (
            sessionValue &&
            entry.startTime - lastSessionEntry.startTime < 1000 &&
            entry.startTime - firstSessionEntry.startTime < 5000
          ) {
            sessionValue += entry.value;
            sessionEntries.push(entry);
          } else {
            sessionValue = entry.value;
            sessionEntries = [entry];
          }
          // 如果当前会话值大于当前CLS值，则更新CLS及其表项。
          if (sessionValue > clsValue) {
            clsValue = sessionValue;
            resolve({
              type: "layout-shift",
              value: clsValue,
            });
          }
        }
      }
    };
    const observer = new PerformanceObserver(entryHandler);
    observer.observe({ entryTypes: ["layout-shift"], buffered: true });
  });
};
// navigationStart：浏览器处理当前网页的启动时间
// fetchStart：浏览器发起http请求读取文档的毫秒时间戳。
// domainLookupStart：域名查询开始时的时间戳。
// domainLookupEnd：域名查询结束时的时间戳。
// connectStart：http请求开始向服务器发送的时间戳。
// connectEnd：浏览器与服务器连接建立（握手和认证过程结束）的毫秒时间戳。
// requestStart：浏览器向服务器发出http请求时的时间戳。或者开始读取本地缓存时。
// responseStart：浏览器从服务器（或读取本地缓存）收到第一个字节时的时间戳。
// responseEnd：浏览器从服务器收到最后一个字节时的毫秒时间戳。
// domLoading：浏览器开始解析网页DOM结构的时间。
// domInteractive：网页dom树创建完成，开始加载内嵌资源的时间。
// domContentLoadedEventStart：网页DOMContentLoaded事件发生时的时间戳。
// domContentLoadedEventEnd：网页所有需要执行的脚本执行完成时的时间，domReady的时间。
// domComplete：网页dom结构生成时的时间戳。
// loadEventStart：当前网页load事件的回调函数开始执行的时间戳。loadEventEnd：当前网页load事件的回调函数结束运行时的时间戳。
